#pragma once

#include<iostream>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<functional>
#include<string>
#include<pthread.h>

#include"Log.hpp"
#include"InetAddr.hpp"
#include"PthreadPool.hpp"

class Server;

class HandlerArg
{
public:
    HandlerArg(Server* self,int sockfd,InetAddr client_addr)
    :_self(self),
    _sockfd(sockfd),
    _client_addr(client_addr)
    {}

    ~HandlerArg()
    {}

    Server* _self;
    int _sockfd;
    InetAddr _client_addr;
};

using serve_fun=std::function<std::string(std::string)>;

class Server
{
public:
    Server(int port,serve_fun func)
    :_port(port),
    _is_running(false),
    _func(func)
    {   
        //1.创建监听套接字
        _listen_sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(_listen_sockfd<0)
        {
            Log(FATAL,"create listen_sockfd error\n");
            exit(-1);
        }
        Log(DEBUG,"create listen_sockfd successfully\n");

        //2.绑定端口号
        sockaddr_in addr;
        bzero(&addr,sizeof(addr));
        addr.sin_family=AF_INET;
        addr.sin_port=_port;
        addr.sin_addr.s_addr=INADDR_ANY;

        if(0<bind(_listen_sockfd,(struct sockaddr*)(&addr),sizeof(addr)))
        {
            Log(FATAL,"bind error\n");
            exit(-1);
        }
        Log(DEBUG,"bind successfully\n");

        //开启监听
        if(0>listen(_listen_sockfd,7))
        {
            Log(FATAL,"listen error\n");
            exit(-1);
        }
        Log(DEBUG,"listen successfully\n");
    }

    ~Server()
    {
        if(_listen_sockfd>0)
        {
            close(_listen_sockfd);
        }
    }

    void Serve(int sockfd,InetAddr client_addr)
    {
        //已经获取客户端地址和文件描述符，可以开始服务
        while(_is_running)
        {
            char buf[1024];
            int rn=read(sockfd,buf,sizeof(buf));
            if(rn<0)
            {
                Log(ERROR,"read error\n");
                continue;
            }
            else if(0==rn)
            {
                Log(DEBUG,"client quit\n");
                break;
            }
            buf[rn]=0;

            //对读取到的数据进行处理，并将处理结果发送给客户端
            std::string tmp = _func(buf);
        
            char response[1024];
            strcpy(response,tmp.c_str());
            int wn=write(sockfd,response,sizeof(response));
            if(wn<0)
            {
                Log(ERROR,"response error\n");
                continue;
            }
            Log(DEBUG,"response successfully\n");
        }
        close(sockfd);
    }

    static void* Handler(void * _arg)
    {
        pthread_detach(pthread_self());
        HandlerArg* arg=(HandlerArg*)(_arg);
        arg->_self->Serve(arg->_sockfd,arg->_client_addr);
        delete arg;
        return nullptr;
    }

    void Start()
    {
        _is_running=true;
        while(_is_running)
        {
            struct sockaddr_in client_addr;
            bzero(&client_addr,sizeof(client_addr));
            socklen_t len=sizeof(client_addr);
            int fd=accept(_listen_sockfd,(struct sockaddr*)(&client_addr),&len);
            if(fd<0)
            {
                Log(ERROR,"accept client link error\n");
                continue;
            }
            Log(DEBUG,"accept client link successfully\n");

            //采用线程去处理
            pthread_t pt;
            HandlerArg *arg=new HandlerArg(this,fd,InetAddr(client_addr));
            if(pthread_create(&pt,nullptr,Handler,arg)<0)
            {
                Log(ERROR,"create pthread error\n");
            }
        }
    }

private:
    serve_fun _func;
    int _listen_sockfd;
    int _port;
    bool _is_running;
};